﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using NUnit.Framework;

namespace TaskFramework.Tests
{
    [TestFixture]
    public class CompositeTransportFixture
    {
        [Test]
        public void should_fire_an_event_from_an_io_module()
        {
            IInputOutputModule ioModule = new InputOutputModule();

            int eventCount = 0;

            ioModule.EventFired += delegate { eventCount++; };
            ioModule.Start();

            Thread.Sleep(50); // wait for processing to finish

            Assert.AreEqual(3, eventCount);
        }

        [Test]
        public void should_verify_that_a_transport_recieves_io_module_events()
        {
            IInputOutputModule ioModule = new InputOutputModule();

            ITestableTransport transport = new Transport();
            transport.AddIOModule(ioModule);

            transport.Start();

            Thread.Sleep(50); // wait for processing to finish

            Assert.AreEqual(3, transport.IOModuleEventRecievedCount);
        }

        //[Test]
        //public void should_create_a_transport()
        //{
        //    IInputOutputModule ioModule = new InputOutputModule();
        //    ICodec codec = new NullCodec();
        //    IEventMapper mapper = new EventMapper();

        //    ITransport transport = new Transport();
        //    transport.AddIOModule(ioModule);
        //    transport.AddCodec(codec);
        //    transport.Mapper = mapper;

        //    int eventCount = 0;

        //    transport.EventFired += delegate { eventCount++; };
            

        //    transport.Start();

        //    Thread.Sleep(100); // wait for processing to finish

        //    Assert.AreEqual(3, eventCount);
        //}
    }

    public class TransportComponentStatistics
    {
        public int EventsRecieved { get; set; }
        public int EventsSent { get; set; }
    }

    public class RawEvent
    {
    }

    public delegate void RawEventHandler(RawEvent e);

    public delegate void EventFiredHandler(MappedEvent e);

    public class MappedEvent
    {
        public object GetCustomEventObject()
        {
            return new object();
        }
    }

    internal interface ITestableTransport : ITransport
    {
        int IOModuleEventRecievedCount { get; }
    }

    internal class Transport : ITestableTransport
    {
        private int _moduleEventRecievedCount;

        private IInputOutputModule _module;

        public event EventFiredHandler EventFired;

        public void AddIOModule(IInputOutputModule module)
        {
            _module = module;
        }

        public void AddCodec(ICodec codec)
        {
            
        }

        public IEventMapper Mapper
        {
            get;
            set;
        }

        public void Start()
        {
            _module.EventFired += new RawEventHandler(module_EventFired);
            _module.Start();
        }

        private void module_EventFired(RawEvent e)
        {
            _moduleEventRecievedCount++;
        }

        public int IOModuleEventRecievedCount
        {
            get { return _moduleEventRecievedCount; }
        }
    }

    internal interface ITransport
    {
        event EventFiredHandler EventFired;
        void AddIOModule(IInputOutputModule module);
        void AddCodec(ICodec codec);
        IEventMapper Mapper { get; set; }
        void Start();
    }

    internal class EventMapper : IEventMapper
    {
    }

    internal interface IEventMapper
    {
    }

    internal class NullCodec : ICodec
    {
    }

    internal interface ICodec
    {
    }

    internal class InputOutputModule : IInputOutputModule
    {
        public event RawEventHandler EventFired;

        public void Start()
        {
            Thread ioEventThread = new Thread(IOEventThread);
            ioEventThread.IsBackground = true;
            ioEventThread.Start();
        }

        private void IOEventThread()
        {
            for (int i = 0; i < 3; i++)
            {
                if (EventFired != null)
                {
                    EventFired(new RawEvent());
                }
            }
        }
    }

    internal interface IInputOutputModule
    {
        event RawEventHandler EventFired;
        void Start();
    }
}
